function [err_abs,err_abs_field,err_rel,err_rel_field] = ...
  numdiff(A,B,varargin)
% Loop over all the fields of the two structires A and B and find the
% maximum absolute and relative errors.

  if(nargin>2)
    err_abs = varargin{1};
    err_abs_field = varargin{2};
    err_rel = varargin{3};
    err_rel_field = varargin{4};
    new_field = varargin{5};
  else
    err_abs = 0;
    err_abs_field = '';
    err_rel = 0;
    err_rel_field = '';
    new_field = 'X';
  end

  %disp(["Comparing fields '",new_field,"'"]);

  switch class(A)

   case "struct"
    A_fields = fieldnames(A);
    for i=1:length(A_fields)
      if(isfield(B,A_fields{i}))
        [err_abs,err_abs_field,err_rel,err_rel_field] = ...
	                          numdiff(getfield(A,A_fields{i}), ...
	                                  getfield(B,A_fields{i}), ...
	              err_abs,err_abs_field,err_rel,err_rel_field, ...
	              [new_field,'.',A_fields{i}]);
      else
        warning(["Field '",A_fields{i},"' is present in A but not in B."]);
      endif
    end

   case "double"
    e_loc = norm(A(:)-B(:));
    den = 0.5*(norm(A(:))+norm(B(:)));
    if(den>0)
      e_rel = e_loc/den;
    else
      e_rel = 0;
    endif
    if(e_loc>err_abs)
      err_abs = e_loc;
      err_abs_field = new_field;
    endif
    if(e_rel>err_rel)
      err_rel = e_rel;
      err_rel_field = new_field;
    endif

   case "cell"
    for i=1:length(A)
      [err_abs,err_abs_field,err_rel,err_rel_field] = ...
             numdiff(A{i},B{i},err_abs,err_abs_field, ...
             err_rel,err_rel_field,new_field);
    end

   case "char"
    % ignore char fields

   otherwise
    error(["Unknown type '",class(A),"'."]);
  endswitch

return
